#include <QtGui>
#include "QtStra_Template.h"
//#include "QtStra2_InstTableDelegate.h"
//#include "QtStra3_InstTableDelegate.h"
#include "QtStra_InstEdit.h"






QtStraTemplate::QtStraTemplate(int straindex, QDockWidget* instDock, QDockWidget* strategyDock, QTabWidget::TabPosition pos, QWidget *parent): QTabWidget(parent)
{
	//set parent property
	setTabPosition(pos);

	m_straindex = straindex;

	//m_pstra1userdata = NULL;
	//m_pstra2userdata = NULL;
	//m_pstra3userdata = NULL;

	if (1 == m_straindex)
	{
		m_xmlfile = "strategy1_userdata.xml";

		//m_pstra1userdata = new QtStraUserdataCore<userdata_stra1>();
	}	
	else if (2 == m_straindex)
	{
		m_xmlfile = "strategy2_userdata.xml";

		//m_pstra2userdata = new QtStraUserdataCore<userdata_stra2>();
	}		
	else if (3 == m_straindex)
	{
		m_xmlfile = "strategy3_userdata.xml";

		//m_pstra3userdata = new QtStraUserdataCore<userdata_stra3>();
	}
		
	m_pstrauserdata = new QtStraUserdata(m_straindex);

	

	m_xml = new QtStraXml( (char*)m_xmlfile.c_str() );

	//set child widget property
	CreateInstInfo(instDock);

	CreateStrategyInfo(strategyDock);


}




void QtStraTemplate::CreateInstInfo(QDockWidget* instDock)
{
	//save StrategyDock
	m_instDock = instDock;


	//Create Strategy Table 
	{

		/*m_instTable = new QTableWidget();
		if (1 == m_straindex || 2 == m_straindex)
			m_instTable->setItemDelegate(new QtStra2InstTableDelegate);
		else if (3 == m_straindex)
			m_instTable->setItemDelegate(new QtStra3InstTableDelegate);
		m_instTable->setSelectionBehavior(QAbstractItemView::SelectRows);
		m_instTable->setAlternatingRowColors(true);*/

		//CreateInstTable();

	}


	//Create spliterBtn to be pushed into dockSplitter
	QSplitter* spliterBtn1 = new QSplitter(Qt::Horizontal);
	QSplitter* spliterBtn2 = new QSplitter(Qt::Horizontal);
	{
		m_ctlBtn = new QPushButton(tr("Start"));
		m_editBtn = new QPushButton(tr("Edit"));
		m_readXmlBtn = new QPushButton(tr("ReadXml"));
		m_writeXmlBtn = new QPushButton(tr("WriteXml"));
		connect(m_ctlBtn, SIGNAL(clicked()), this, SLOT(OnctlBtnClicked()));
		connect(m_editBtn, SIGNAL(clicked()), this, SLOT(OneditBtnClicked()));
		connect(m_readXmlBtn, SIGNAL(clicked()), this, SLOT(OnreadxmlBtnClicked()));
		connect(m_writeXmlBtn, SIGNAL(clicked()), this, SLOT(OnwritexmlBtnClicked()));


		spliterBtn1->addWidget(m_ctlBtn);
		spliterBtn1->addWidget(m_editBtn);
		spliterBtn2->addWidget(m_readXmlBtn);
		spliterBtn2->addWidget(m_writeXmlBtn);


	}




	//Create dockSplitter to be pushed into dockWidget
	{

		m_instSplitter = new QSplitter(Qt::Vertical);
		//m_instSplitter->addWidget(m_instTable);
		m_instSplitter->addWidget(spliterBtn1);
		m_instSplitter->addWidget(spliterBtn2);
		//m_instSplitter->setStretchFactor(0, 1);
	}



}


void QtStraTemplate::CreateStrategyInfo(QDockWidget* strategyDock)
{

	m_strategyDock = strategyDock;

	m_strategyinfo = new QtStraStrategyInfo();

}





void QtStraTemplate::OnUpdateInstDockAndStrategyDock()
{
	//update m_instDock
	{
		//QSplitter* child = static_cast<QSplitter*>(m_strategyDock->widget());
		QWidget* child = (m_instDock->widget());

		if (child)
		{
			child->hide();
		}

		if (1 == m_straindex)
			m_instDock->setWindowTitle(tr("Inst1_Info"));
		else if (2 == m_straindex)
			m_instDock->setWindowTitle(tr("Inst2_Info"));
		else if (3 == m_straindex)
			m_instDock->setWindowTitle(tr("Inst3_Info"));
		


		
		m_instDock->setWidget(m_instSplitter);
	}

	//update strategyDock
	{
		QWidget* child = /*static_cast<QtStraStrategyInfo*>*/(m_strategyDock->widget());

		if (child)
		{
			child->hide();
		}

		if (1 == m_straindex)
			m_strategyDock->setWindowTitle(tr("Strategy1_Info"));
		else if (2 == m_straindex)
			m_strategyDock->setWindowTitle(tr("Strategy2_Info"));
		else if (3 == m_straindex)
			m_strategyDock->setWindowTitle(tr("Strategy3_Info"));
		

		
		m_strategyDock->setWidget(m_strategyinfo);
	}



}


void QtStraTemplate::SetInstTable(QTableWidget* instTable)
{
	m_instTable = instTable;

	m_instSplitter->insertWidget(0, m_instTable);

	m_instSplitter->setStretchFactor(0, 1);
}

void QtStraTemplate::InitInstTable()
{
	//first clear
	m_instTable->clear();

	//init row/column cnt and  headlables
	vector<char*> tablehead;
	if (m_xml->GetColumnName(tablehead))
	{
		m_instTable->setRowCount(0);
		m_instTable->setColumnCount(tablehead.size());

		QStringList headerLabels;

		for( vector<char*>::iterator it = tablehead.begin(); it != tablehead.end(); it++)
		{
			headerLabels << *it;
		}

		m_instTable->setHorizontalHeaderLabels(headerLabels);
	}
}

void QtStraTemplate::CreateThread()
{
	CStrategySys* pStrategy = NULL;

	if (1 == m_straindex)
		pStrategy = new CStrategyUser1("strategy_user1");
	if (2 == m_straindex)
		pStrategy = new CStrategyUser2("strategy_user2");
	else if (3 == m_straindex)
		pStrategy = new CStrategyUser3("strategy_user3");


	if (pStrategy)
	{
		//create thread
		m_thread = new QtStraThread(pStrategy, this);

		if (m_thread)
		{
			connect(m_thread->FrameEvent(), SIGNAL(SignalInit(BarSeries*, BarData*)),
				this, SLOT(OnSlotInit(BarSeries*, BarData*)), Qt::BlockingQueuedConnection);

			connect(m_thread->FrameEvent(), SIGNAL(SignalDestroy(BarInfo*)),
				this, SLOT(OnSlotDestroy(BarInfo*)), Qt::BlockingQueuedConnection);


			connect(m_thread->StrategySys(), SIGNAL(SignalSysMd(BarData*)),
				this, SLOT(OnSlotSysMd(BarData*)));




			m_thread->Start();
		}
		else
			pantheios::log_ERROR("[CreateThread] m_thread init failed");


	}
	else
		pantheios::log_ERROR("[CreateThread] pStrategy init failed");




}

void QtStraTemplate::DestroyThread()
{
	if (m_thread)
	{
		delete m_thread;
		m_thread = NULL;
	}

}

void QtStraTemplate::OnDestroyAllBars()
{
	/*********************Set m_instTable unchecked*********************************/

	m_pstrauserdata->SetOldFromNew();

	m_pstrauserdata->ClearNew();


	//if (1 == m_straindex)
	//{
	//	m_pstra1userdata->SetOld(m_pstra1userdata->GetNew());

	//	vector<QtStraUserdataCore<userdata_stra1>::QtStraData> tmp;

	//	//set empty
	//	m_pstra1userdata->SetNew(tmp);



	//}
	//else if (2 == m_straindex)
	//{
	//	m_pstra2userdata->SetOld(m_pstra2userdata->GetNew());

	//	vector<QtStraUserdataCore<userdata_stra2>::QtStraData> tmp;

	//	//set empty
	//	m_pstra2userdata->SetNew(tmp);



	//}
	//else if (3 == m_straindex)
	//{
	//	m_pstra3userdata->SetOld(m_pstra3userdata->GetNew());

	//	vector<QtStraUserdataCore<userdata_stra3>::QtStraData> tmp;

	//	//set empty
	//	m_pstra3userdata->SetNew(tmp);



	//}
	//




	/**********************************************************************************************/

	/*********************StartCtl*********************************/

	StartCtl(TimerFire_namespace::appreinitfiretimer);

	/**********************************************************************************************/
}

void QtStraTemplate::OnReinitAllBars()
{
	//-------------2. recover all data from m_stra2_vbarrltold-----------------------------------------------


	m_pstrauserdata->SwapOldAndNew();
	
	//vector<QtStraUserdataCore<userdata_stra1>::QtStraData> oldtmp;

	//vector<QtStraUserdataCore<userdata_stra1>::QtStraData> newtmp;

	//m_pstrauserdata->GetOld(oldtmp);

	//m_pstrauserdata->GetNew(newtmp);

	//m_pstrauserdata->SetNew(oldtmp);

	//m_pstrauserdata->SetOld(newtmp);


	//if (1 == m_straindex)
	//{

	//	//vector<QtStraUserdataCore<userdata_stra1>::QtStraData> tmp = m_pstra1userdata->GetNew();

	//	//m_pstra1userdata->SetNew(m_pstra1userdata->GetOld());

	//	//m_pstra1userdata->SetOld(tmp);


	//}
	//else if (2 == m_straindex)
	//{

	///*	vector<QtStraUserdataCore<userdata_stra2>::QtStraData> tmp = m_pstra2userdata->GetNew();

	//	m_pstra2userdata->SetNew(m_pstra2userdata->GetOld());

	//	m_pstra2userdata->SetOld(tmp);*/



	//}
	//else if (3 == m_straindex)
	//{

	//	//vector<QtStraUserdataCore<userdata_stra3>::QtStraData> tmp = m_pstra3userdata->GetNew();

	//	//m_pstra3userdata->SetNew(m_pstra3userdata->GetOld());

	//	//m_pstra3userdata->SetOld(tmp);

	//}




	//-------------------------------------------------------------------------------------------------------


	/*********************StartCtl*********************************/

	StartCtl(TimerFire_namespace::appreinitfiretimer);

	/**********************************************************************************************/

}

void QtStraTemplate::OnTimer(TimerFire_namespace::TimerFireType timertype)
{
	if (m_thread)
		m_thread->SendTimerData(timertype);
}


void QtStraTemplate::OnctlBtnClicked()
{
	QString str = m_ctlBtn->text();

	if (str == "Start")
	{
		//disable all
		m_instTable->setEnabled(false);
		m_ctlBtn->setEnabled(false);
		m_editBtn->setEnabled(false);
		m_readXmlBtn->setEnabled(false);
		m_writeXmlBtn->setEnabled(false);


		StartCtl();


		m_ctlBtn->setText("End");
		m_ctlBtn->setEnabled(true);
	}
	else if (str == "End")
	{

		m_ctlBtn->setText("Start");
		m_instTable->setEnabled(true);
		m_editBtn->setEnabled(true);
		m_readXmlBtn->setEnabled(true);
		m_writeXmlBtn->setEnabled(true);
	}

}

void QtStraTemplate::OneditBtnClicked()
{
	QtStraInstEdit* QEdit = new QtStraInstEdit(*m_instTable, this);

	if (QEdit->exec())
	{


	}

	if (QEdit)
	{

		m_instSplitter->insertWidget(0, m_instTable);

		delete QEdit;
	}



}

void QtStraTemplate::OnreadxmlBtnClicked()
{
	ReadXml();
}

void QtStraTemplate::OnwritexmlBtnClicked()
{
	WriteXml();
}

void QtStraTemplate::OnSlotInit(BarSeries* pBarSer, BarData* pData)
{

	pantheios::log_WARNING("[OnSlotInit] ", pData->inst, " index:", panint(pData->index), " tickcnt:", panint(pData->tickcnt));


	QtInstrument* pInst = new QtInstrument(m_strategyinfo, pBarSer, pData);

	if (pInst)
	{
		int index = addTab(pInst, tr(pData->inst));

	}


	if (pData)
		delete pData;




}

void QtStraTemplate::OnSlotDestroy(BarInfo* pbar)
{
	pantheios::log_WARNING("[OnSlotDestroy] ", pbar->instru);




	int tabcnt = count();

	for (int index = 0; index < tabcnt; index++)
	{
		QString text = tabText(index);

		if (string(pbar->instru) == text.toStdString() )
		{
			QtInstrument* pInst = static_cast<QtInstrument*>(widget(index));

			removeTab(index);


			if (pInst)
				delete pInst;

			tabcnt = count();
		}

	}


}

void QtStraTemplate::OnSlotSysMd(BarData* pData)
{
	//pantheios::log_WARNING("[OnSlotSysMd] ", pData->inst, " index:", panint(pData->index), " tickcnt:", panint(pData->tickcnt));


	int tabcnt = count();

	for (int index = 0; index < tabcnt; index++)
	{
		QString text = tabText(index);

		if (string(pData->inst) == text.toStdString() )
		{
			QtInstrument* pInst = static_cast<QtInstrument*>(widget(index));

			if (pInst)
			{
				pInst->MdUpdate(pData);
			}
		}

	}



	if (pData)
		delete pData;


}

void QtStraTemplate::ReadXml()
{
	////first clear
	//m_instTable->clear();

	////init row/column cnt and  headlables
	//vector<char*> tablehead;
	//if (m_xml->GetColumnName(tablehead))
	//{
	//	m_instTable->setRowCount(0);
	//	m_instTable->setColumnCount(tablehead.size());

	//	QStringList headerLabels;

	//	for( vector<char*>::iterator it = tablehead.begin(); it != tablehead.end(); it++)
	//	{
	//		headerLabels << *it;
	//	}

	//	m_instTable->setHorizontalHeaderLabels(headerLabels);
	//}

	InitInstTable();


	//read xml and insert table
	int rowcnt = 0, colcnt = 0;

	if (m_xml->GetRowAndColCnt(rowcnt, colcnt))
	{
		for (int rowIndex = 0; rowIndex < rowcnt; rowIndex++)
		{
			vector < pair<char*, char*> > attriRow;

			//read row from xml
			m_xml->ReadXml(rowIndex, attriRow);

			char destInst[10] = {0};
			if (CStrategySys::ConvertXml(attriRow[0].second, destInst))
			{

				int tablerowcnt = m_instTable->rowCount();

				//insert row to table
				m_instTable->insertRow(tablerowcnt);


				//insert column
				for (int colIndex = 0; colIndex < colcnt; colIndex++)
				{
					QTableWidgetItem *item = NULL;

					if (0 == colIndex)
					{
						item = new QTableWidgetItem(destInst);

						item->setCheckState(Qt::Unchecked);
					}
					else
						item = new QTableWidgetItem(attriRow[colIndex].second);

					item->setTextAlignment(Qt::AlignCenter);

					m_instTable->setItem(tablerowcnt, colIndex, item);
				}

			}
			else
			{
				char buf[150] = {0};
				sprintf(buf, "%s (%s)\n" "don't exist in mapPdt.\n", attriRow[0].second, m_xmlfile.c_str());


				int r = QMessageBox::warning(this, tr("TF"),
					tr(buf),
					QMessageBox::Cancel);
			}


		}
	}




}

void QtStraTemplate::WriteXml()
{
	// ----------------------1.Clear all xml in memory--------------------------------------------------

	//user may add or remove instrument, so first clear then add them to xml
	if (false == m_xml->ClearXml())
	{
		pantheios::log_ERROR("[QtStraTemplate::WriteXml] ClearXml Error");
		return;
	}

	//m_xml->SaveFile();

	// -----------------------------------------------------------------------------------------------



	// ----------------------2.Insert xml in m_instTable--------------------------------------------------

	int rowcnt = m_instTable->rowCount();

	int colcnt = m_instTable->columnCount();


	for (int rowIndex = 0; rowIndex < rowcnt; rowIndex++)
	{
		vector < pair<char*, char*> > attriRow;


		for (int colIndex = 0; colIndex < colcnt; colIndex++)
		{
			QString strname = m_instTable->horizontalHeaderItem(colIndex)->text();

			QString strvalue = m_instTable->item(rowIndex, colIndex)->text();


			string stdstrname = (strname.toStdString());

			string stdstrvalue = (strvalue.toStdString());


			char* cname = new char[stdstrname.size() + 5]; 
			memcpy(cname, stdstrname.c_str(), stdstrname.size() + 1);


			char* cvalue = new char[stdstrvalue.size() + 5];
			memcpy(cvalue, stdstrvalue.c_str(), stdstrvalue.size() + 1);


			if ( 0 == colIndex)
			{
				memset(cvalue, 0, stdstrvalue.size() + 5);
				if (CStrategySys::ConvertInst((char*)stdstrvalue.c_str(), cvalue))
				{
					attriRow.push_back( make_pair(cname, cvalue) );
				}
				else
					pantheios::log_ERROR("[QtStraTemplate::WriteXml] ConvertInst Error");

			}
			else
			{

				attriRow.push_back( make_pair(cname, cvalue) );
			}


		}		


		//write data
		if (false == m_xml->WriteXml(attriRow))
		{
			pantheios::log_ERROR("[QtStraTemplate::WriteXml] WriteXml Error");
		}


		//free memory
		for (vector < pair<char*, char*> >::iterator it = attriRow.begin(); it != attriRow.end(); it++)
		{
			if (it->first)
				delete [] (it->first);

			if (it->second)
				delete [] (it->second);

		}

	}


	m_xml->SaveFile();
	// -----------------------------------------------------------------------------------------------


}



void QtStraTemplate::StartCtl(TimerFire_namespace::TimerFireType timertype)
{


	/*****************Update m_stra1thd1_vbarrltold and m_stra1thd1_vbarrltnew**********************/

	//change from ui
	if (TimerFire_namespace::invalid == timertype)
	{
		m_pstrauserdata->SetOldFromNew();



		//if (1 == m_straindex)
		//{
		//	//m_pstra1userdata->SetOld(m_pstra1userdata->GetNew());

		//	
		//}
		//else if (2 == m_straindex)
		//{
		//	//m_pstra2userdata->SetOld(m_pstra2userdata->GetNew());


		//}
		//else if (3 == m_straindex)
		//{
		//	//m_pstra3userdata->SetOld(m_pstra3userdata->GetNew());

		//}
		
		


		SetUserdataNew();
		


		
	}


	/***************************************************************************************************/


	//1.call member function to calculate Edit/Del/Add Inst
	//2.send data to FrameEvent thread 
	Edit_Del_AddInst(timertype);




}



void QtStraTemplate::Edit_Del_AddInst(TimerFire_namespace::TimerFireType timertype)
{
	vector<MFCData*> vpmfcdata;


	/*****************Update vpmfcdata with Edit/Del/Add Inst**************/

	if (false == m_pstrauserdata->EditInst(timertype, vpmfcdata))
	{
		printf("[Edit_Del_AddInst] EditInst failed\n");
		return;
	}

	if (false == m_pstrauserdata->DelInst(timertype, vpmfcdata))
	{
		printf("[Edit_Del_AddInst] DelInst failed\n");
		return;
	}

	if (false == m_pstrauserdata->AddInst(timertype, vpmfcdata))
	{
		printf("[Edit_Del_AddInst] AddInst failed\n");
		return;
	}

	/*
	if (1 == m_straindex)
	{
	if (false == m_pstra1userdata->EditInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] EditInst failed\n");
	return;
	}

	if (false == m_pstra1userdata->DelInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] DelInst failed\n");
	return;
	}

	if (false == m_pstra1userdata->AddInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] AddInst failed\n");
	return;
	}
	}
	else if (2 == m_straindex)
	{
	if (false == m_pstra2userdata->EditInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] EditInst failed\n");
	return;
	}

	if (false == m_pstra2userdata->DelInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] DelInst failed\n");
	return;
	}

	if (false == m_pstra2userdata->AddInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] AddInst failed\n");
	return;
	}
	}
	else if (3 == m_straindex)
	{
	if (false == m_pstra3userdata->EditInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] EditInst failed\n");
	return;
	}

	if (false == m_pstra3userdata->DelInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] DelInst failed\n");
	return;
	}

	if (false == m_pstra3userdata->AddInst(timertype, vpmfcdata))
	{
	printf("[Edit_Del_AddInst] AddInst failed\n");
	return;
	}
	}*/




	/************************************************************************/



	//send mfc data
	if (m_thread)
		m_thread->SendMFCData(vpmfcdata);




	//delete vpmfcdata 
	typedef vector<MFCData*>::iterator it_vpmfcdata;
	for (it_vpmfcdata itpmfc = vpmfcdata.begin(); itpmfc != vpmfcdata.end() ; itpmfc++)
	{
		MFCData* &pmfcdata = *itpmfc;

		if (pmfcdata)
		{
			delete pmfcdata;
			pmfcdata = NULL;
		}


	}

}

